home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 May / EnigmA AMIGA RUN 18 (1997)(G.R. Edizioni)(IT)[!][issue 1997-05][EAR-CD II].iso / ghost / gs403src_gs.lha / gs4.03 / gxcmap.c < prev    next >
C/C++ Source or Header  |  1996-09-04  |  21KB  |  622 lines

  1. /* Copyright (C) 1992, 1996 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of Aladdin Ghostscript.
  4.   
  5.   Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  6.   or distributor accepts any responsibility for the consequences of using it,
  7.   or for whether it serves any particular purpose or works at all, unless he
  8.   or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  9.   License (the "License") for full details.
  10.   
  11.   Every copy of Aladdin Ghostscript must include a copy of the License,
  12.   normally in a plain ASCII text file named PUBLIC.  The License grants you
  13.   the right to copy, modify and redistribute Aladdin Ghostscript, but only
  14.   under certain conditions described in the License.  Among other things, the
  15.   License requires that the copyright notice and this notice be preserved on
  16.   all copies.
  17. */
  18.  
  19. /* gxcmap.c */
  20. /* Color mapping for Ghostscript */
  21. #include "gx.h"
  22. #include "gserrors.h"
  23. #include "gsccolor.h"
  24. #include "gxcspace.h"
  25. #include "gxfarith.h"
  26. #include "gxfrac.h"
  27. #include "gxdcconv.h"
  28. #include "gxdevice.h"
  29. #include "gxcmap.h"
  30. #include "gxlum.h"
  31. #include "gzstate.h"
  32. #include "gxdither.h"
  33.  
  34. /* Structure descriptor */
  35. public_st_device_color();
  36. #define cptr ((gx_device_color *)vptr)
  37. private ENUM_PTRS_BEGIN(device_color_enum_ptrs) {
  38.     struct_proc_enum_ptrs((*proc)) = cptr->type->enum_ptrs;
  39.     if ( proc == 0 )
  40.       return 0;
  41.     return (*proc)(vptr, size, index, pep);
  42. } ENUM_PTRS_END
  43. private RELOC_PTRS_BEGIN(device_color_reloc_ptrs) {
  44.     struct_proc_reloc_ptrs((*proc)) = cptr->type->reloc_ptrs;
  45.     if ( proc != 0 )
  46.       (*proc)(vptr, size, gcst);
  47. } RELOC_PTRS_END
  48. #undef cptr
  49.  
  50. /* ------ Trace device mapping procedures ------ */
  51.  
  52. /* If DEBUG is defined, these procedures substitute for direct calls */
  53. /* on the device map_{rgb,cmyk}_color procedures. */
  54.  
  55. gx_color_index
  56. gx_proc_map_rgb_color(gx_device *dev,
  57.   gx_color_value vr, gx_color_value vg, gx_color_value vb)
  58. {    gx_color_index cindex =
  59.       (*dev_proc(dev, map_rgb_color))(dev, vr, vg, vb);
  60.     if_debug5('C', "%s [C]RGB %u,%u,%u -> color 0x%lx\n",
  61.           dev->dname, (uint)vr, (uint)vg, (uint)vb, (ulong)cindex);
  62.     return cindex;
  63. }
  64.  
  65. gx_color_index
  66. gx_proc_map_rgb_alpha_color(gx_device *dev,
  67.   gx_color_value vr, gx_color_value vg, gx_color_value vb, gx_color_value va)
  68. {    gx_color_index cindex =
  69.       (*dev_proc(dev, map_rgb_alpha_color))(dev, vr, vg, vb, va);
  70.     if_debug6('C', "[C]%s RGBA %u,%u,%u,%u -> color 0x%lx\n",
  71.           dev->dname, (uint)vr, (uint)vg, (uint)vb, (uint)va,
  72.           (ulong)cindex);
  73.     return cindex;
  74. }
  75.  
  76. gx_color_index
  77. gx_proc_map_cmyk_color(gx_device *dev,
  78.   gx_color_value vc, gx_color_value vm, gx_color_value vy, gx_color_value vk)
  79. {    gx_color_index cindex =
  80.       (*dev_proc(dev, map_cmyk_color))(dev, vc, vm, vy, vk);
  81.     if_debug6('C', "[C]%s CMYK %u,%u,%u,%u -> color 0x%lx\n",
  82.           dev->dname, (uint)vc, (uint)vm, (uint)vy, (uint)vk,
  83.           (ulong)cindex);
  84.     return cindex;
  85. }
  86.  
  87. /* ---------------- Device color rendering ---------------- */
  88.  
  89. private cmap_proc_gray(cmap_gray_halftoned);
  90. private cmap_proc_gray(cmap_gray_direct);
  91. private cmap_proc_gray(cmap_gray_to_rgb_halftoned);
  92. private cmap_proc_gray(cmap_gray_to_rgb_direct);
  93. private cmap_proc_gray(cmap_gray_to_cmyk_halftoned);
  94. private cmap_proc_gray(cmap_gray_to_cmyk_direct);
  95. private cmap_proc_rgb(cmap_rgb_halftoned);
  96. private cmap_proc_rgb(cmap_rgb_direct);
  97. private cmap_proc_rgb(cmap_rgb_to_gray_halftoned);
  98. private cmap_proc_rgb(cmap_rgb_to_gray_direct);
  99. private cmap_proc_rgb(cmap_rgb_to_cmyk);
  100. #define cmap_cmyk_halftoned cmap_cmyk_direct
  101. private cmap_proc_cmyk(cmap_cmyk_direct);
  102. private cmap_proc_cmyk(cmap_cmyk_to_gray);
  103. private cmap_proc_cmyk(cmap_cmyk_to_rgb);
  104.  
  105. private const gx_color_map_procs
  106.   cmap_gray_few =
  107.    { cmap_gray_halftoned, cmap_rgb_to_gray_halftoned, cmap_cmyk_to_gray },
  108.   cmap_gray_many =
  109.    { cmap_gray_direct, cmap_rgb_to_gray_direct, cmap_cmyk_to_gray },
  110.   cmap_rgb_few =
  111.    { cmap_gray_to_rgb_halftoned, cmap_rgb_halftoned, cmap_cmyk_to_rgb },
  112.   cmap_rgb_many =
  113.    { cmap_gray_to_rgb_direct, cmap_rgb_direct, cmap_cmyk_to_rgb },
  114.   cmap_cmyk_few =
  115.    { cmap_gray_to_cmyk_halftoned, cmap_rgb_to_cmyk, cmap_cmyk_halftoned },
  116.   cmap_cmyk_many =
  117.    { cmap_gray_to_cmyk_direct, cmap_rgb_to_cmyk, cmap_cmyk_direct };
  118.  
  119. const gx_color_map_procs *cmap_procs_default = &cmap_gray_many;
  120.  
  121. private const gx_color_map_procs _ds *cmap_few[] = {
  122.     0, &cmap_gray_few, 0, &cmap_rgb_few, &cmap_cmyk_few
  123. };
  124.  
  125. private const gx_color_map_procs _ds *cmap_many[] = {
  126.     0, &cmap_gray_many, 0, &cmap_rgb_many, &cmap_cmyk_many
  127. };
  128.  
  129. /* Determine the color mapping procedures for a device. */
  130. const gx_color_map_procs *
  131. gx_device_cmap_procs(const gx_device *dev)
  132. {    return ((gx_device_has_color(dev) ? dev->color_info.max_color :
  133.          dev->color_info.max_gray) >= 31 ? cmap_many : cmap_few)
  134.         [dev->color_info.num_components];
  135. }
  136.  
  137. /* Set the color mapping procedures in the graphics state. */
  138. void
  139. gx_set_cmap_procs(gs_state *pgs)
  140. {    pgs->cmap_procs = gx_device_cmap_procs(pgs->device);
  141. }
  142.  
  143. /* Remap the color in the graphics state. */
  144. int
  145. gx_remap_color(gs_state *pgs)
  146. {    const gs_color_space *pcs = pgs->color_space;
  147.     return (*pcs->type->remap_color)(pgs->ccolor, pcs, pgs->dev_color, pgs);
  148. }
  149.  
  150. /* Indicate that a color space has no underlying concrete space. */
  151. const gs_color_space *
  152. gx_no_concrete_space(const gs_color_space *pcs, const gs_state *pgs)
  153. {    return NULL;
  154. }
  155.  
  156. /* Indicate that a color space is concrete. */
  157. const gs_color_space *
  158. gx_same_concrete_space(const gs_color_space *pcs, const gs_state *pgs)
  159. {    return pcs;
  160. }
  161.  
  162. /* Indicate that a color cannot be concretized. */
  163. int
  164. gx_no_concretize_color(const gs_client_color *pcc, const gs_color_space *pcs,
  165.   frac *pconc, const gs_state *pgs)
  166. {    return_error(gs_error_rangecheck);
  167. }
  168.  
  169. /* By default, remap a color by concretizing it and then */
  170. /* remapping the concrete color. */
  171. int
  172. gx_default_remap_color(const gs_client_color *pcc, const gs_color_space *pcs,
  173.   gx_device_color *pdc, const gs_state *pgs)
  174. {    frac conc[4];
  175.     const gs_color_space *pconcs;
  176.     int code = (*pcs->type->concretize_color)(pcc, pcs, conc, pgs);
  177.     if ( code < 0 )
  178.       return code;
  179.     pconcs = cs_concrete_space(pcs, pgs);
  180.     return (*pconcs->type->remap_concrete_color)(conc, pdc, pgs);
  181. }
  182.  
  183. /* Color remappers for the standard color spaces. */
  184. /* Note that we use D... instead of Device... in some places because */
  185. /* gcc under VMS only retains 23 characters of procedure names. */
  186.  
  187. #define unit_frac(v, ftemp)\
  188.   (ftemp = (v),\
  189.    (is_fneg(ftemp) ? frac_0 : is_fge1(ftemp) ? frac_1 : float2frac(ftemp)))
  190.  
  191. /* DeviceGray */
  192. int
  193. gx_concretize_DeviceGray(const gs_client_color *pc, const gs_color_space *pcs,
  194.   frac *pconc, const gs_state *pgs)
  195. {    float ftemp;
  196.     pconc[0] = unit_frac(pc->paint.values[0], ftemp);
  197.     return 0;
  198. }
  199. int
  200. gx_remap_concrete_DGray(const frac *pconc,
  201.   gx_device_color *pdc, const gs_state *pgs)
  202. {    (*pgs->cmap_procs->map_gray)
  203.         (pconc[0], pdc, pgs);
  204.     return 0;
  205. }
  206. int
  207. gx_remap_DeviceGray(const gs_client_color *pc, const gs_color_space *pcs,
  208.   gx_device_color *pdc, const gs_state *pgs)
  209. {    float ftemp;
  210.     (*pgs->cmap_procs->map_gray)
  211.         (unit_frac(pc->paint.values[0], ftemp),
  212.          pdc, pgs);
  213.     return 0;
  214. }
  215.  
  216. /* DeviceRGB */
  217. int
  218. gx_concretize_DeviceRGB(const gs_client_color *pc, const gs_color_space *pcs,
  219.   frac *pconc, const gs_state *pgs)
  220. {    float ftemp;
  221.     pconc[0] = unit_frac(pc->paint.values[0], ftemp);
  222.     pconc[1] = unit_frac(pc->paint.values[1], ftemp);
  223.     pconc[2] = unit_frac(pc->paint.values[2], ftemp);
  224.     return 0;
  225. }
  226. int
  227. gx_remap_concrete_DRGB(const frac *pconc,
  228.   gx_device_color *pdc, const gs_state *pgs)
  229. {    gx_remap_concrete_rgb(pconc[0], pconc[1], pconc[2], pdc, pgs);
  230.     return 0;
  231. }
  232. int
  233. gx_remap_DeviceRGB(const gs_client_color *pc, const gs_color_space *pcs,
  234.   gx_device_color *pdc, const gs_state *pgs)
  235. {    float ft0, ft1, ft2;
  236.     gx_remap_concrete_rgb(unit_frac(pc->paint.values[0], ft0),
  237.                   unit_frac(pc->paint.values[1], ft1),
  238.                   unit_frac(pc->paint.values[2], ft2),
  239.                   pdc, pgs);
  240.     return 0;
  241. }
  242.  
  243. /* DeviceCMYK */
  244. int
  245. gx_concretize_DeviceCMYK(const gs_client_color *pc, const gs_color_space *pcs,
  246.   frac *pconc, const gs_state *pgs)
  247. {    float ftemp;
  248.     pconc[0] = unit_frac(pc->paint.values[0], ftemp);
  249.     pconc[1] = unit_frac(pc->paint.values[1], ftemp);
  250.     pconc[2] = unit_frac(pc->paint.values[2], ftemp);
  251.     pconc[3] = unit_frac(pc->paint.values[3], ftemp);
  252.     return 0;
  253. }
  254. int
  255. gx_remap_concrete_DCMYK(const frac *pconc,
  256.   gx_device_color *pdc, const gs_state *pgs)
  257. {    gx_remap_concrete_cmyk(pconc[0], pconc[1], pconc[2], pconc[3], pdc, pgs);
  258.     return 0;
  259. }
  260. int
  261. gx_remap_DeviceCMYK(const gs_client_color *pc, const gs_color_space *pcs,
  262.   gx_device_color *pdc, const gs_state *pgs)
  263. {    float ft0, ft1, ft2, ft3;
  264.     gx_remap_concrete_cmyk(unit_frac(pc->paint.values[0], ft0),
  265.                    unit_frac(pc->paint.values[1], ft1),
  266.                    unit_frac(pc->paint.values[2], ft2),
  267.                    unit_frac(pc->paint.values[3], ft3),
  268.                    pdc, pgs);
  269.     return 0;
  270. }
  271.  
  272. /* ------ Render Gray color. ------ */
  273.  
  274. private void
  275. cmap_gray_halftoned(frac gray, gx_device_color *pdc, const gs_state *pgs)
  276. {    if ( gx_render_gray(gx_map_color_frac(pgs, gray, effective_transfer.colored.gray), pdc, pgs) == 1 )
  277.       gx_color_load(pdc, pgs);
  278. }
  279.  
  280. private void
  281. cmap_gray_direct(frac gray, gx_device_color *pdc, const gs_state *pgs)
  282. {    gx_device *dev = gs_currentdevice_inline(pgs);
  283.     frac mgray = gx_map_color_frac(pgs, gray, effective_transfer.colored.gray);
  284.     gx_color_value cv_gray = frac2cv(mgray);
  285.     gx_color_index color =
  286.       (pgs->alpha == gx_max_color_value ?
  287.        gx_map_rgb_color(dev, cv_gray, cv_gray, cv_gray) :
  288.        gx_map_rgb_alpha_color(dev, cv_gray, cv_gray, cv_gray, pgs->alpha));
  289.     if ( color == gx_no_color_index )
  290.     {    if ( gx_render_gray(mgray, pdc, pgs) == 1 )
  291.           gx_color_load(pdc, pgs);
  292.         return;
  293.     }
  294.     color_set_pure(pdc, color);
  295. }
  296.  
  297. private void
  298. cmap_gray_to_rgb_halftoned(frac gray, gx_device_color *pdc,
  299.   const gs_state *pgs)
  300. {    cmap_rgb_halftoned(gray, gray, gray, pdc, pgs);
  301. }
  302.  
  303. private void
  304. cmap_gray_to_rgb_direct(frac gray, gx_device_color *pdc, const gs_state *pgs)
  305. {    cmap_rgb_direct(gray, gray, gray, pdc, pgs);
  306. }
  307.  
  308. private void
  309. cmap_gray_to_cmyk_halftoned(frac gray, gx_device_color *pdc,
  310.   const gs_state *pgs)
  311. {    /*
  312.      * Per the last paragraph of section 6.3 (p. 309) of the
  313.      * PostScript Language Reference Manual, 2nd Edition,
  314.      * we must bypass the C, M, and Y transfer functions in this case.
  315.      */
  316.     frac mgray = gx_map_color_frac(pgs, gray, effective_transfer.colored.gray);
  317.     if ( gx_render_gray(mgray, pdc, pgs) == 1 )
  318.       gx_color_load(pdc, pgs);
  319. }
  320.  
  321. private void
  322. cmap_gray_to_cmyk_direct(frac gray, gx_device_color *pdc,
  323.   const gs_state *pgs)
  324. {    /*
  325.      * Per the last paragraph of section 6.3 (p. 309) of the
  326.      * PostScript Language Reference Manual, 2nd Edition,
  327.      * we must bypass the C, M, and Y transfer functions in this case.
  328.      */
  329.     frac mgray = gx_map_color_frac(pgs, gray, effective_transfer.colored.gray);
  330.     frac mblack = frac_1 - mgray;
  331.     gx_device *dev = gs_currentdevice_inline(pgs);
  332.     gx_color_index color =
  333.       gx_map_cmyk_color(dev,
  334.                 frac2cv(frac_0), frac2cv(frac_0),
  335.                 frac2cv(frac_0), frac2cv(mblack));
  336.     if ( color != gx_no_color_index )
  337.     {    color_set_pure(pdc, color);
  338.         return;
  339.     }
  340.     if ( gx_render_gray(mgray, pdc, pgs) == 1 )
  341.       gx_color_load(pdc, pgs);
  342. }
  343.  
  344. /* ------ Render RGB color. ------ */
  345.  
  346. /*
  347.  * This code should test r == g and g == b and then use the gray
  348.  * rendering procedures.  The Adobe documentation allows this:
  349.  * conversion between color spaces occurs before the transfer function
  350.  * and halftoning.  However, output from FrameMaker (mis)uses the
  351.  * transfer function to provide the equivalent of indexed color;
  352.  * it requires the color components to be passed through unchanged.
  353.  * For this reason, we have to make the check after the transfer
  354.  * function rather than before.
  355.  *
  356.  * Since this procedure is used so heavily, we duplicate most of its code
  357.  * rather than making a text for color_info.max_color >= 31.
  358.  */
  359.  
  360. private void
  361. cmap_rgb_halftoned(frac r, frac g, frac b, gx_device_color *pdc,
  362.   const gs_state *pgs)
  363. {    frac mred = gx_map_color_frac(pgs, r, effective_transfer.colored.red);
  364.     frac mgreen = gx_map_color_frac(pgs, g, effective_transfer.colored.green);
  365.     frac mblue = gx_map_color_frac(pgs, b, effective_transfer.colored.blue);
  366.     if ( (mred == mgreen && mred == mblue ?    /* gray shade */
  367.           gx_render_gray(mred, pdc, pgs) :
  368.           gx_render_rgb(mred, mgreen, mblue, pdc, pgs)) == 1 )
  369.       gx_color_load(pdc, pgs);
  370. }
  371.  
  372. private void
  373. cmap_rgb_direct(frac r, frac g, frac b, gx_device_color *pdc,
  374.   const gs_state *pgs)
  375. {    gx_device *dev = gs_currentdevice_inline(pgs);
  376.     frac mred = gx_map_color_frac(pgs, r, effective_transfer.colored.red);
  377.     frac mgreen = gx_map_color_frac(pgs, g, effective_transfer.colored.green);
  378.     frac mblue = gx_map_color_frac(pgs, b, effective_transfer.colored.blue);
  379.     gx_color_index color =
  380.       (pgs->alpha == gx_max_color_value ?
  381.        gx_map_rgb_color(dev, frac2cv(mred), frac2cv(mgreen),
  382.                 frac2cv(mblue)) :
  383.        gx_map_rgb_alpha_color(dev, frac2cv(mred), frac2cv(mgreen),
  384.                   frac2cv(mblue), pgs->alpha));
  385.     if ( color != gx_no_color_index )
  386.       {    color_set_pure(pdc, color);
  387.         return;
  388.       }
  389.     if ( (mred == mgreen && mred == mblue ?    /* gray shade */
  390.           gx_render_gray(mred, pdc, pgs) :
  391.           gx_render_rgb(mred, mgreen, mblue, pdc, pgs)) == 1 )
  392.       gx_color_load(pdc, pgs);
  393. }
  394.  
  395. private void
  396. cmap_rgb_to_gray_halftoned(frac r, frac g, frac b, gx_device_color *pdc,
  397.   const gs_state *pgs)
  398. {    cmap_gray_halftoned(color_rgb_to_gray(r, g, b, pgs), pdc, pgs);
  399. }
  400.  
  401. private void
  402. cmap_rgb_to_gray_direct(frac r, frac g, frac b, gx_device_color *pdc,
  403.   const gs_state *pgs)
  404. {    cmap_gray_direct(color_rgb_to_gray(r, g, b, pgs), pdc, pgs);
  405. }
  406.  
  407. private void
  408. cmap_rgb_to_cmyk(frac r, frac g, frac b, gx_device_color *pdc,
  409.   const gs_state *pgs)
  410. {    frac cmyk[4];
  411.     color_rgb_to_cmyk(r, g, b, pgs, cmyk);
  412.     (*pgs->cmap_procs->map_cmyk)(cmyk[0], cmyk[1], cmyk[2], cmyk[3], pdc, pgs);
  413. }
  414.  
  415. /* ------ Render CMYK color. ------ */
  416.  
  417. private void
  418. cmap_cmyk_to_gray(frac c, frac m, frac y, frac k, gx_device_color *pdc, const gs_state *pgs)
  419. {    (*pgs->cmap_procs->map_gray)(color_cmyk_to_gray(c, m, y, k, pgs), pdc, pgs);
  420. }
  421.  
  422. private void
  423. cmap_cmyk_direct(frac c, frac m, frac y, frac k, gx_device_color *pdc,
  424.   const gs_state *pgs)
  425. {    gx_device *dev = gs_currentdevice_inline(pgs);
  426.     frac mcyan = frac_1 - gx_map_color_frac(pgs, frac_1 - c, effective_transfer.colored.red);
  427.     frac mmagenta = frac_1 - gx_map_color_frac(pgs, frac_1 - m, effective_transfer.colored.green);
  428.     frac myellow = frac_1 - gx_map_color_frac(pgs, frac_1 - y, effective_transfer.colored.blue);
  429.     frac mblack = frac_1 - gx_map_color_frac(pgs, frac_1 - k, effective_transfer.colored.gray);
  430.     /* We make a test for direct vs. halftoned, rather than */
  431.     /* duplicating most of the code of this procedure. */
  432.     if ( dev->color_info.max_color >= 31 )
  433.     {    gx_color_index color =
  434.             gx_map_cmyk_color(dev,
  435.                       frac2cv(mcyan), frac2cv(mmagenta),
  436.                       frac2cv(myellow), frac2cv(mblack));
  437.         if ( color != gx_no_color_index )
  438.         {    color_set_pure(pdc, color);
  439.             return;
  440.         }
  441.     }
  442.     /* Don't convert colors with C = M = Y to gray shades: */
  443.     /* on a CMYK device, this may produce quite different output. */
  444.     if ( gx_render_cmyk(mcyan, mmagenta, myellow, mblack, pdc, pgs) == 1 )
  445.       gx_color_load(pdc, pgs);
  446. }
  447.  
  448. private void
  449. cmap_cmyk_to_rgb(frac c, frac m, frac y, frac k, gx_device_color *pdc, const gs_state *pgs)
  450. {    frac rgb[3];
  451.     color_cmyk_to_rgb(c, m, y, k, pgs, rgb);
  452.     (*pgs->cmap_procs->map_rgb)(rgb[0], rgb[1], rgb[2], pdc, pgs);
  453. }
  454.  
  455. /* ------ Transfer function mapping ------ */
  456.  
  457. #if FRAC_MAP_INTERPOLATE        /* NOTA BENE */
  458.  
  459. /* Map a color fraction through a transfer map. */
  460. /* We only use this if we are interpolating. */
  461. frac
  462. gx_color_frac_map(frac cv, const frac *values)
  463. {
  464. #define cp_frac_bits (frac_bits - log2_transfer_map_size)
  465.     int cmi = frac2bits_floor(cv, log2_transfer_map_size);
  466.     frac mv = values[cmi];
  467.     int rem, mdv;
  468.     /* Interpolate between two adjacent values if needed. */
  469.     rem = cv - bits2frac(cmi, log2_transfer_map_size);
  470.     if ( rem == 0 ) return mv;
  471.     mdv = values[cmi + 1] - mv;
  472. #if arch_ints_are_short
  473.     /* Only use long multiplication if necessary. */
  474.     if ( mdv < -1 << (16 - cp_frac_bits) ||
  475.          mdv > 1 << (16 - cp_frac_bits)
  476.        )
  477.         return mv + (uint)(((ulong)rem * mdv) >> cp_frac_bits);
  478. #endif
  479.     return mv + ((rem * mdv) >> cp_frac_bits);
  480. #undef cp_frac_bits
  481. }
  482.  
  483. #endif                    /* FRAC_MAP_INTERPOLATE */
  484.  
  485. /* ------ Default device color mapping ------ */
  486.  
  487. /* RGB mapping for black-and-white devices */
  488.  
  489. /* White-on-black */
  490. gx_color_index
  491. gx_default_w_b_map_rgb_color(gx_device *dev,
  492.   gx_color_value r, gx_color_value g, gx_color_value b)
  493. {    /* Map values >= 1/2 to 1, < 1/2 to 0. */
  494.     return ((r | g | b) > gx_max_color_value / 2 ?
  495.         (gx_color_index)1 : (gx_color_index)0);
  496. }
  497. int
  498. gx_default_w_b_map_color_rgb(gx_device *dev, gx_color_index color,
  499.   gx_color_value prgb[3])
  500. {    /* Map 1 to max_value, 0 to 0. */
  501.     prgb[0] = prgb[1] = prgb[2] = -(gx_color_value)color;
  502.     return 0;
  503. }
  504. /* Black-on-white */
  505. gx_color_index
  506. gx_default_b_w_map_rgb_color(gx_device *dev,
  507.   gx_color_value r, gx_color_value g, gx_color_value b)
  508. {    /* Map values >= 1/2 to 0, < 1/2 to 1. */
  509.     return ((r | g | b) > gx_max_color_value / 2 ?
  510.         (gx_color_index)0 : (gx_color_index)1);
  511. }
  512. int
  513. gx_default_b_w_map_color_rgb(gx_device *dev, gx_color_index color,
  514.   gx_color_value prgb[3])
  515. {    /* Map 0 to max_value, 1 to 0. */
  516.     prgb[0] = prgb[1] = prgb[2] = -((gx_color_value)color ^ 1);
  517.     return 0;
  518. }
  519.  
  520. /* RGB mapping for gray-scale devices */
  521.  
  522. gx_color_index
  523. gx_default_gray_map_rgb_color(gx_device *dev,
  524.   gx_color_value r, gx_color_value g, gx_color_value b)
  525. {    /* We round the value rather than truncating it. */
  526.     gx_color_value gray =
  527.         ((r * (ulong)lum_red_weight) +
  528.          (g * (ulong)lum_green_weight) +
  529.          (b * (ulong)lum_blue_weight) +
  530.          (lum_all_weights / 2)) / lum_all_weights
  531.         * dev->color_info.max_gray / gx_max_color_value;
  532.     return gray;
  533. }
  534.  
  535. int
  536. gx_default_gray_map_color_rgb(gx_device *dev, gx_color_index color,
  537.   gx_color_value prgb[3])
  538. {    gx_color_value gray =
  539.         color * gx_max_color_value / dev->color_info.max_gray;
  540.     prgb[0] = gray;
  541.     prgb[1] = gray;
  542.     prgb[2] = gray;
  543.     return 0;
  544. }
  545.  
  546. /* RGB mapping for 24-bit true (RGB) color devices */
  547.  
  548. gx_color_index
  549. gx_default_rgb_map_rgb_color(gx_device *dev,
  550.   gx_color_value r, gx_color_value g, gx_color_value b)
  551. {    if ( dev->color_info.depth == 24 )
  552.         return gx_color_value_to_byte(b) +
  553.             ((uint)gx_color_value_to_byte(g) << 8) +
  554.             ((ulong)gx_color_value_to_byte(r) << 16);
  555.     else
  556.     {    uint bits_per_color = dev->color_info.depth / 3;
  557.         ulong max_value = (1 << bits_per_color) - 1;
  558.  
  559.         return ((r * max_value / gx_max_color_value) << (bits_per_color * 2)) +
  560.             ((g * max_value / gx_max_color_value) << (bits_per_color)) +
  561.             (b * max_value / gx_max_color_value);
  562.     }
  563. }
  564.  
  565. /* Map a color index to a r-g-b color. */
  566. int
  567. gx_default_rgb_map_color_rgb(gx_device *dev, gx_color_index color,
  568.   gx_color_value prgb[3])
  569. {    if ( dev->color_info.depth == 24 )
  570.     {    prgb[0] = gx_color_value_from_byte(color >> 16);
  571.         prgb[1] = gx_color_value_from_byte((color >> 8) & 0xff);
  572.         prgb[2]    = gx_color_value_from_byte(color & 0xff);
  573.     }
  574.     else
  575.     {    uint bits_per_color = dev->color_info.depth / 3;
  576.         uint color_mask = (1 << bits_per_color) - 1;
  577.  
  578.         prgb[0] = ((color >> (bits_per_color * 2)) & color_mask) *
  579.             (ulong)gx_max_color_value / color_mask;
  580.         prgb[1] = ((color >> (bits_per_color)) & color_mask) *
  581.             (ulong)gx_max_color_value / color_mask;
  582.         prgb[2] = (color & color_mask) *
  583.             (ulong)gx_max_color_value / color_mask;
  584.     }
  585.     return 0;
  586. }
  587.  
  588. /* CMYK mapping for RGB devices (should never be called!) */
  589.  
  590. gx_color_index
  591. gx_default_map_cmyk_color(gx_device *dev,
  592.   gx_color_value c, gx_color_value m, gx_color_value y, gx_color_value k)
  593. {    /* Convert to RGB */
  594.     frac rgb[3];
  595.     color_cmyk_to_rgb(cv2frac(c), cv2frac(m), cv2frac(y), cv2frac(k),
  596.               NULL, rgb);
  597.     return gx_map_rgb_color(dev, frac2cv(rgb[0]),
  598.                 frac2cv(rgb[1]), frac2cv(rgb[2]));
  599. }
  600.  
  601. /* CMYK mapping for CMYK devices */
  602.  
  603. gx_color_index
  604. gx_default_cmyk_map_cmyk_color(gx_device *dev,
  605.   gx_color_value c, gx_color_value m, gx_color_value y, gx_color_value k)
  606. {    gx_color_index color =
  607.       (gx_color_value_to_byte(k) +
  608.        ((uint)gx_color_value_to_byte(y) << 8)) +
  609.       ((ulong)(gx_color_value_to_byte(m) +
  610.            ((uint)gx_color_value_to_byte(c) << 8)) << 16);
  611.  
  612.     return (color == gx_no_color_index ? color ^ 1 : color);
  613. }
  614.  
  615. /* Default mapping from RGB-alpha to RGB. */
  616.  
  617. gx_color_index
  618. gx_default_map_rgb_alpha_color(gx_device *dev,
  619.   gx_color_value r, gx_color_value g, gx_color_value b, gx_color_value alpha)
  620. {    return gx_map_rgb_color(dev, r, g, b);
  621. }
  622.